package tt.dz.biz.service.rpc;

import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.avro.Protocol;
import org.apache.avro.Protocol.Message;
import org.apache.avro.Schema;
import org.apache.avro.Schema.Field;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericData.Record;
import org.apache.avro.io.Decoder;
import org.apache.avro.ipc.generic.GenericResponder;
import tt.dz.biz.dao.common.RpcAccessWhiteListDAO;
import tt.dz.common.AppContxtUtil;
import tt.dz.common.BusinessException;
import tt.dz.common.DzConstants;
import tt.dz.common.DzErrorCode;
import tt.dz.common.DzErrorCode.ExceptionErrorCode;
import tt.dz.common.LogUtil;

public class RPCInterfaceService
  extends GenericResponder
{
  public RPCInterfaceService(Protocol protocol)
  {
    super(protocol);
  }
  
  public Object respond(Protocol.Message message, Object request)
    throws Exception
  {
    return respond(message, request, getLocal());
  }
  
  public Object readRequest(Schema actual, Schema expected, Decoder in)
    throws IOException
  {
    Object obj = super.readRequest(actual, expected, in);
    if ((obj instanceof GenericData.Record))
    {
      String ip = in.readString();
      GenericData.Record record = (GenericData.Record)obj;
      Schema schema = record.getSchema();
      List<Schema.Field> fields = schema.getFields();
      List<Schema.Field> _fields = new ArrayList();
      Schema.Field ipField = new Schema.Field("ip", null, null, null);
      for (Schema.Field field : fields)
      {
    	  Schema.Field _field = new Schema.Field(field.name(), field.schema(), field.doc(), field.defaultValue());
        _fields.add(_field);
      }
      Schema.Field _field;
      _fields.add(ipField);
      Schema schema1 = Schema.createRecord(_fields);
      GenericData.Record record1 = new GenericData.Record(schema1);
      for (Schema.Field f : fields) {
        record1.put(f.name(), record.get(f.name()));
      }
      record1.put("ip", ip);
      return record1;
    }
    return obj;
  }
  
  protected Object respond(Protocol.Message message, Object request, Protocol protocol)
    throws Exception
  {
    JSONObject resultJson = new JSONObject();
    if ((request instanceof GenericData.Record))
    {
      GenericData.Record record = (GenericData.Record)request;
      String localIp = InetAddress.getLocalHost().getHostAddress();
      String ip = (String)record.get("ip");
      LogUtil.info("RPC客户端请求IP:" + ip);
      if ((!localIp.equals(ip)) && (!"127.0.0.1".equals(ip)))
      {
        RpcAccessWhiteListDAO rpcAccessWhiteListDAO = (RpcAccessWhiteListDAO)AppContxtUtil.getBean("rpcAccessWhiteListDAO");
        boolean accessable = rpcAccessWhiteListDAO.CheckClientIP(ip);
        LogUtil.debug("RPC客户端请求IP:" + ip + "，校验结果：" + (accessable ? "通过" : "不通过"));
        if (!accessable)
        {
          resultJson.put("isSuccess", Integer.valueOf(0));
          resultJson.put("errorMsg", "请求IP地址" + ip + "不合法，不能够做RPC调用");
          resultJson.put("errorCode", DzErrorCode.ExceptionErrorCode.COMMON_EXCEPTION.value());
          return resultJson.toJSONString();
        }
        LogUtil.info("IP:" + ip + "校验通过 ");
      }
      else
      {
        LogUtil.info("本机访问不做校验");
      }
    }
    try
    {
      long begin = System.currentTimeMillis();
      String methodName = message.getName();
      LogUtil.info("  RCP 接口" + methodName + "：start……，接受参数为：" + request);
      
      RPCBaseService service = (RPCBaseService)AppContxtUtil.getBean(DzConstants.METHOD_SERVICE_MAP.get( methodName));
      Object obj = service.execute(message, request, protocol);
      LogUtil.info("  RCP 接口" + methodName + "：end……，耗时：" + (System.currentTimeMillis() - begin) + "毫秒,接受参数为：" + request + ",返回参数为：" + obj);
      return obj;
    }
    catch (BusinessException e)
    {
      LogUtil.error("RPC接口异常，参数为：" + request, e);
      resultJson.put("isSuccess", Integer.valueOf(0));
      resultJson.put("errorMsg", e.getStatusDescribe());
      resultJson.put("errorCode", e.getStatusCode());
      return resultJson.toJSONString();
    }
    catch (Exception e)
    {
      LogUtil.error("RPC接口异常，参数为：" + request, e);
      resultJson.put("isSuccess", Integer.valueOf(0));
      resultJson.put("errorMsg", e.getMessage());
      resultJson.put("errorCode", DzErrorCode.ExceptionErrorCode.COMMON_EXCEPTION.value());
    }
    return resultJson.toJSONString();
  }
}
